﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.IO;

using log4net;

namespace SaveAWatt.Server
{
    public class WebServer
    {
        // Logger
        //
        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private int port = 8080;
        private TcpListener server;

        public void Initialise()
        {
            try
            {
                System.Console.WriteLine("[WebServer] HTTP server attempting to start on port {0}", port);

                // Create a listener.
                IPAddress localAddr = IPAddress.Parse("127.0.0.1");
                server = new TcpListener(localAddr, port);
            }
            catch (Exception e)
            {
                System.Console.WriteLine("WebServer] Error: {0}", e);
            }
        }

        public void Listen () {
            try
            {
                // Start listening for client requests
                server.Start();

                System.Console.WriteLine("[WebServer] Web server listening...");

                // Enter the listening loop
                while (true)
                {
                    // Buffer for reading data
                    Byte[] bytes = new Byte[1024];
                    String data = null;

                    // This method blocks while waiting for requests
                    TcpClient client = server.AcceptTcpClient();
                    System.Console.WriteLine("[WebServer] Client connected...");

                    // Get a stream object for reading and writing
                    NetworkStream stream = client.GetStream();
                    int bytesRead = stream.Read(bytes, 0, bytes.Length);

                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, bytesRead);
                    Console.WriteLine("[WebServer] Received: {0} bytes", bytesRead);

                    // HTTP was "GET" request
                    if (data.Substring(0, 3) == "GET")
                    {
                        int startPosition;

                        // Look for HTTP Request
                        startPosition = data.IndexOf("HTTP", 1);
                        // Get the HTTP text and version
                        string HTTPversion = data.Substring(startPosition, 8);

                        // Extract the requested type and file/directory
                        string request = data.Substring(0, startPosition - 1);

                        // Replace backslash with forwardslash
                        request.Replace("\\", "/");

                        // If filename is not supplied, add forward slash to indicate
                        // that it is a directory and then we will look for the
                        // default file name
                        if ((request.IndexOf(".") < 1) && (!request.EndsWith("/")))
                        {
                            request = request + "/";
                        }

                        startPosition = request.LastIndexOf("/") + 1;
                        string fileReq = request.Substring(startPosition);

                        string dirName = request.Substring(request.IndexOf("/"),
                                                           request.LastIndexOf("/") - 3);

                        // Do this until we move the compilation directory
                        dirName = "../../.." + dirName;

                        // Try to find the file
                        string filePath = dirName + fileReq;
                        StringWriter response = new StringWriter();
                        if (File.Exists(filePath))
                        {
                            response.Write(File.ReadAllText(filePath));
                        }
                        // File not found error
                        else
                        {
                            response.Write("404 File not found");
                        }

                        // Send back a response
                        byte[] responseBytes = System.Text.Encoding.ASCII.GetBytes(response.ToString());
                        stream.Write(responseBytes, 0, responseBytes.Length);
                        Console.WriteLine("[WebServer] Sent: {0} bytes", responseBytes.Length);
                    }
                    else
                    {
                        Console.WriteLine("[WebServer] Client requested unsupported method");
                    }

                    // Shutdown and end connection
                    client.Close();
                }
            }
            catch (SocketException e)
            {
                System.Console.WriteLine("[WebServer] SocketException: {0}", e);
            }
            finally
            {
                // Stop listening for clients
                server.Stop();
            }
        }

        public void Close()
        {
            server.Stop();
        }
    }
}
